package com.zy.explore.generator.infrastructure.core;

import com.zy.explore.generator.infrastructure.core.util.DataBeanUtil;
import com.zy.explore.generator.infrastructure.core.util.StrUtil;
import com.zy.explore.generator.interfaces.frm.generator.AssemblerFrm;
import com.zy.explore.generator.interfaces.frm.generator.FacadeFrm;
import com.zy.explore.generator.interfaces.frm.generator.FeignFrm;
import com.zy.explore.generator.interfaces.frm.generator.PersistFrm;
import com.zy.explore.generator.interfaces.frm.generator.QueryFrm;
import com.zy.explore.generator.interfaces.frm.generator.SaveFrm;
import com.zy.explore.generator.interfaces.frm.generator.ServiceFrm;
import com.zy.explore.generator.interfaces.frm.generator.ValidatorFrm;
import com.zy.explore.generator.interfaces.frm.generator.VoFrm;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.time.LocalDateTime;
import java.util.Properties;

/**
 * 建类说明：代码生成核心类
 * <p>
 * 参数--> 找到对应模板 --> 替换参数生成新文件，存放位置
 * <p>
 * 当前版本：1.0.0
 *
 * @author 中国印
 * @date 2022年01月09日 21:34:43
 * @since 1.0.0
 */
@Slf4j
@Service
public class GenerateCore {

    public static Properties init() throws IOException {
        Properties properties = new Properties();
        // 使用ClassLoader加载properties配置文件生成对应的输入流
        InputStream in = GenerateCore.class.getClassLoader().getResourceAsStream("generator/genConfig.properties");
        // 使用properties对象加载输入流
        properties.load(in);
        assert in != null;
        in.close();
        return properties;
    }

    public static void doGenerateFile(Object frm, String tplName, String tplPath, String targetFilePath) throws Exception {
        // 要生成的文件对象(文件绝对位置 + 文件名称[带后缀])
        File file = new File(targetFilePath);
        // 写入文件
        writeFile(tplName, tplPath, frm, file);
        log.info("创建文件{}成功 {}", targetFilePath, file.getPath());
    }

    /**
     * 方法说明：获取模板
     *
     * @param ftl     ftl模板名称
     * @param ftlPath ftl模板路径
     * @return {@link Template }
     * @throws IOException IO流异常
     */
    public static Template getTemplate(String ftl, String ftlPath) throws IOException {
        Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
        String userDir = System.getProperty("user.dir");
        File file = new File(userDir + ftlPath);
        cfg.setDirectoryForTemplateLoading(file);
        cfg.setDefaultEncoding("UTF-8");
        return cfg.getTemplate(ftl, "UTF-8");
    }

    /**
     * 方法说明：根据模板填充参数生成文件
     *
     * @param ftl        ftl模板名称
     * @param ftlPath    ftl模板路径
     * @param dataModel  数据模型map结构
     * @param targetFile 目标文件
     * @throws IOException       IO异常
     * @throws TemplateException 模板异常
     */
    public static void writeFile(String ftl, String ftlPath, Object dataModel, File targetFile) throws IOException, TemplateException {
        if (!targetFile.exists()) {
            if (!targetFile.getParentFile().exists()) {
                targetFile.getParentFile().mkdirs();
            }
            targetFile.createNewFile();
        }
        if (StringUtils.isEmpty(ftl)) {
            return;
        }
        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(targetFile));
        try {
            getTemplate(ftl, ftlPath).process(dataModel, outputStreamWriter);
        } finally {
            outputStreamWriter.flush();
            outputStreamWriter.close();
        }
    }

    public static void main(String[] args) throws Exception {
        Properties config = GenerateCore.init();
        String[] tableNames = StrUtil.underlineToHumpFirstUpperCase(config.getProperty("tableNames")).split(",");
        String artifactId = config.getProperty("artifactId");
        String feignProjectName = artifactId + "-feign";
        String providerProjectName = artifactId + "-provider";
        String rootPath = config.getProperty("targetRootPath");
        String basePackageName = config.getProperty("basePackageName");
        Boolean common = Boolean.valueOf(config.getProperty("common"));
        for (String firstUpperHumpTableName : tableNames) {
            //region 1.生成Feign类
            FeignFrm jpaFeignFrm = FeignFrm.builder()
                    .basePackageName(basePackageName)
                    .common(common)
                    .tableClassNamePrefix(firstUpperHumpTableName)
                    .tableName(StrUtil.humpToUnderline(firstUpperHumpTableName))
                    .authorName(config.getProperty("authorName"))
                    .dateTime(LocalDateTime.now().toString())
                    .propTableName(StrUtil.firstCaseToLower(firstUpperHumpTableName))
                    .build();
            GenerateFramework.generateFeign(config, jpaFeignFrm, rootPath, feignProjectName, firstUpperHumpTableName);
            //endregion

            //region 2.生成Facade类
            FacadeFrm facadeFrm = DataBeanUtil.copyOf(jpaFeignFrm, FacadeFrm.class);
            GenerateFramework.generateFacade(config, facadeFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 3.生成Assembler类
            AssemblerFrm assemblerFrm = new AssemblerFrm();
            GenerateFramework.generateAssembler(config, assemblerFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 4.生成Validator类
            ValidatorFrm validatorFrm = new ValidatorFrm();
            GenerateFramework.generateValidator(config, validatorFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 5.生成Service类
            ServiceFrm serviceFrm = new ServiceFrm();
            GenerateFramework.generateService(config, serviceFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 6.生成持久层
            PersistFrm persistFrm = new PersistFrm();
            GenerateFramework.generatePersistLayer(config, persistFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 7.生成QueryFrm.java类
            QueryFrm queryFrm = new QueryFrm();
            GenerateFramework.generateQueryFrm(config, queryFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 8.生成SaveFrm.java类
            SaveFrm saveFrm = new SaveFrm();
            GenerateFramework.generateSaveFrm(config, saveFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion

            //region 9.生成Vo.java类
            VoFrm voFrm = new VoFrm();
            GenerateFramework.generateVo(config, voFrm, rootPath, providerProjectName, firstUpperHumpTableName);
            //endregion
        }
    }

}
